let func1 = () => {
  const P1 = () =>
    new Promise(resolve => {
      console.log('p1')
      setTimeout(() => resolve())
    })
  const P2 = () =>
    new Promise(resolve => {
      console.log('p2')
      resolve()
    })
  setTimeout(() => {
    console.log('s1')
    P1().then(() => {
      console.log(1)
    })
  })
  setTimeout(() => {
    console.log('s2')
    P2().then(() => {
      console.log(2)
    })
  })
}

/**
1000ms并不是定时器执行前的等待时间，而是将定时器中的回调函数加入任务队列前的等待时间。   
*/
let func11 = () => {
  setTimeout(() => {
    console.log('1')
  }, 1000)
  setTimeout(() => {
    console.log('1')
  }, 1000)
}
/**2
 * 异步的是(t) => console.log(t)，而new Promise().then()这一句是同步执行的，它做了什么？
 * 它创建了一个Promise实例，然后调用了实例上的then方法，
 * 告诉Promise，我这里有个callback，你先帮我记录好，等同步跑完了，我的状态也改变了，你再帮我执行它
 */
let func2 = () => {
  new Promise(resolve => {
    resolve(1)
    new Promise(resolve => {
      resolve(2)
    }).then(t => console.log(t))
    console.log(4)
  }).then(t => console.log(t))
  console.log(3)
}
/** 3
 * Promise状态变了callback确实应该立刻执行，但前提是同步代码走完了，且你的callback有先注册进去，.then不是异步，异步的是里面的callback，
 * .then也是在告诉Promise我有个callback需要你存起来，等时机到了，你再帮我执行，这个过程是个异步行为
 */
let fun3 = () => {
  new Promise(resolve => {
    setTimeout(() => {
      resolve(1)
    }, 0)
    new Promise(resolve => {
      setTimeout(() => {
        resolve(2)
      }, 0)
    }).then(t => console.log(t))
    console.log(4)
  }).then(t => console.log(t))
  console.log(3)
}

// 创建Promise对象x1，并在executor函数中执行业务逻辑function
/*  
  console.log('p1',x2)
  console.log(100)
  console.log('p2',x2)
  console.log(101)
  console.log('p3',x2)
*/

function executor(resolve, reject) {
  resolve(100)
}
let x1 = new Promise(executor)
// 内部返回值穿透到最外层, x1延迟绑定回调函数
function onResovle(value) {
  console.log(value)
  let x2 = new Promise((resolve, reject) => resolve(value + 1))
  console.log('p2', x2)
  return x2
}
let x2 = x1.then(onResovle)
console.log('p1', x2)
x2.then(value => {
  console.log(value)
  console.log('p3', x2)
})

/* 

ES7 引入了 async/await，这是 JavaScript 异步编程的一个重大改进，
提供了在不阻塞主线程的情况下用同步代码实现异步访问资源的能力，并且使得代码逻辑更加清晰。
生成器（Generator）函数是一个带星号函数，而且可以暂停和恢复执行。
（1）在生成器函数内部执行一段代码，如果遇到 yield 关键字，
 那么 JavaScript 引擎将返回关键字后面的内容给外部，并暂停该函数的执行。
（2）外部函数可以通过 next 方法恢复函数的执行。

可以把协程看成是跑在线程上的任务，一个线程上可以存在多个协程，但是在线程上同时只能执行一个协程。
　如果从 A 协程启动 B 协程，就把 A 协程称为 B 协程的父协程。
　协程不是被操作系统内核所管理，而完全是由程序所控制（也就是在用户态执行）。
  这样带来的好处就是性能得到了很大的提升，不会像线程切换那样消耗资源。

async/await
async 是一个通过异步执行并隐式返回 Promise 作为结果的函数
当执行到await 100时，会默认创建一个 Promise 对象。
let promise_ = new Promise((resolve,reject){
  resolve(100)
})
 */
async function foo() {
  console.log(1)
  let a = await 100
  console.log(a)
  console.log(2)
}
console.log(0)
foo()
console.log(3)
